<template>
  <div class="form">
    <el-form :model="formData" ref="formRef" :label-width="labelWidth">
      <slot name="header"></slot>
      <el-row>
        <template v-for="item in formItems" :key="item.label">
          <el-col v-bind="colLayout">
            <el-form-item
              :prop="item.field"
              :label="item.label"
              :rules="item.rules"
              :style="itemStyle"
            >
              <template v-if="item.type === 'text' || item.type === 'password'">
                <el-input
                  style="width: 250px"
                  :placeholder="item.placeholder"
                  v-bind="item.otherOptions"
                  :show-password="item.type === 'password'"
                  v-model="formData[`${item.field}`]"
                />
              </template>
              <template v-else-if="item.type === 'select'">
                <el-select
                  :placeholder="item.placeholder"
                  v-bind="item.otherOptions"
                  style="width: 250px"
                  v-model="formData[`${item.field}`]"
                >
                  <el-option
                    v-for="option in item.options"
                    :key="option.value"
                    :value="option.value"
                  ></el-option>
                </el-select>
              </template>
              <template v-else-if="item.type === 'datepicker'">
                <el-date-picker
                  style="width: 250px"
                  type="monthrange"
                  range-separator="到"
                  start-placeholder="开始"
                  end-placeholder="结束"
                  v-model="formData[`${item.field}`]"
                >
                </el-date-picker>
              </template>
            </el-form-item>
          </el-col>
        </template>
      </el-row>
      <el-row class="footer">
        <el-button @click="resetForm" type="primary" icon="el-icon-refresh-left"
          >重置</el-button
        >
        <el-button type="primary" icon="el-icon-search">搜索</el-button>
      </el-row>
    </el-form>
  </div>
</template>

<script setup lang="ts">
// PropType是vue内置的一个能够让我们在接收prop时限定更加具体的类型
import { PropType } from 'vue'
import { IColLayout, IFormItem, IFormLayout } from '../types/type'
import { computed, ref } from '@vue/reactivity'
import { IFormData } from '@/base-ui/form/types/type'
import { ElMenuItem } from 'element-plus'
import { onMounted, watch } from '@vue/runtime-core'
import _ from 'lodash'
const props = defineProps({
  formItems: {
    type: Array as PropType<IFormItem[]>,
    default: () => {}
  },
  formData: {
    type: Object,
    required: true
  },
  labelWidth: {
    type: String,
    default: '100px'
  },
  itemStyle: {
    type: Object,
    default: () => ({
      padding: '10px 40px'
    })
  },
  colLayout: {
    type: Object as PropType<IColLayout>,
    default: () => ({
      xl: 6,
      lg: 8,
      md: 12,
      sm: 24,
      xs: 24
    })
  }
})

// console.log(props.formData)
const emit = defineEmits(['update:formData'])

// 这种方法有弊端
// const formData = computed({
//   get: () => props.formData,
//   set: (newVal) => {
//     console.log('-----') // 这里的值不会打印，因为set没有被触发!
//     emit('update:formData', newVal)
//   }
// })

// 1. 将接收到的prop引用类型的值间接通过深拷贝出一份新对象并通过ref响应式修饰后返回给一个全新的引用
const formData = ref(_.cloneDeep(props.formData))
// 2. 将这个引用应用到模板中各个表单
// 3. 深度监视这个全新的引用是否发生更新，发生更新时，将这个全新的引用通过emit传递给父组件
watch(
  formData,
  (newVal) => {
    // 每一次引用中的各个属性的变更就都能够触发回调了
    // 将最新的值通过emit然后再将深拷贝后的newVal传递给父组件
    emit('update:formData', _.cloneDeep(newVal))
  },
  {
    deep: true // 开启深度监视
  }
)
// 重置
const formRef = ref(null)
const resetForm = () => {
  ;(formRef.value as any).resetFields()
}
</script>

<style scoped lang="less">
.el-input {
  width: 250px;
}
.footer {
  display: flex;
  justify-content: right;
  gap: 20px;
  padding-right: 20px;
}
</style>
